/**
 ************************************************************************************************************
 * Base Application class
 ************************************************************************************************************
 * @file RBApplication.h
 ************************************************************************************************************/

#pragma once

#ifdef  HEADER_MSG
#pragma HEADER_MSG(RBApplication.h)
#endif

/************************************************************************************************************
 * Includes
 ************************************************************************************************************/
#include <RBMain/RBSingleton.h>

#include <RBMain/Dt.h>
#include <RBMain/RBCamera.h>
#include <RBMain/RBHandle.h>
#include <RBMain/RBInput.h>
#include <RBMain/RBRenderer.h>
#include <RBMain/RBTimer.h>

/************************************************************************************************************
 * Forward declarations
 ************************************************************************************************************/
class RBVisibilityManager;

/************************************************************************************************************
 * Class
 ************************************************************************************************************/

struct EMessage
{
    enum Type
    {
        REQUEST_EXIT,
        WINDOW_ACTIVATE,
        WINDOW_INACTIVATE,
        WINDOW_DESTROY,
        ON_KEY,
        ON_MOUSE,
        MOUSE_MOVE

    };

    struct MouseData
    {
        float deltaX;
        float deltaY;
        float posX;
        float posY;
    };

    struct KeyData
    {
        RBInput::KeyType button;
        RBInput::KeyState state;
    };

    union Data
    {
        MouseData mouse;
        KeyData key;
    };

    EMessage(Type eType, Data data) : m_eType(eType), m_data(data) {}
    EMessage() {}

    Type m_eType;
    Data m_data;

};

class RBApplication : public RBSingleton<RBApplication>
{
    RBDeclareRootRTTI(RBApplication);
public:
				                RBApplication		();
	virtual		               ~RBApplication		();

    RBRenderer*                 GetRenderer         () const;

	virtual bool                Init                (RBRenderer* renderer);

    bool                        Open                (const RBString& strFilename);
    void                        Close               ();
    virtual void                OnEntityLoaded		(RBEntityHandle pScene);
    virtual void				OnEntityUnloaded	(RBEntityHandle pScene);
    bool                        Save                (const RBString& strFilename);

    virtual void                OnIdle              ();
    virtual void                Release             ();

    void                        dump_profiler       ();

	// Various callbacks called when receiving events by applications: Win32 / Qt / wxWidgets ...
	virtual void                OnKey               (RBInput::KeyType button, RBInput::KeyState state);
    virtual void                SetMousePos         (const int2& mousePos);

    virtual void                ChangeResolution    (const int2& size);

	RBVisibilityManager*		get_scene			() { return m_main_scene; }
	RBCameraHandle				get_camera			() { return m_camera; }
    void                        set_camera_speed    (float32 camera_speed) { m_camera_speed = camera_speed; }

	// Render scene from view to render_target with technique as ID
	static void					render_scene		(RBVisibilityManager* scene, RBCamera* view, RBRenderer* renderer, RBRenderTargetGroup* render_target, RBStringID technique="");

    uint32                      Width;
    uint32                      Height;

protected:
	virtual RBRenderer*         CreateRenderer      ();

    //////////////////////////////////////////////////////////////////////////
    // Methods overridable by application
    //////////////////////////////////////////////////////////////////////////
    virtual RBVisibilityManager* CreateVisibilityMgr ();

    virtual void                Render              (const Dt& dt);

    virtual void                UpdateCamera        (const Dt& dt);
    //////////////////////////////////////////////////////////////////////////

    Dt                          MeasureTime         ();

    //////////////////////////////////////////////////////////////////////////
    void                        InitCameraNode      ();

    void                        UpdateMouse         ();

protected:
    
	RBRendererPtr	            m_renderer;

    std::vector<RBEntityHandle> m_entities;
    RBVisibilityManager*        m_main_scene;

    float32                     m_fCurrentTime;
    Dt                          m_dt;
    float32                     m_fStepTime;
    float32                     m_camera_speed;


    RBHandle<RBCamera>          m_camera;
    RBEntityHandle              m_spCameraOrbit;
    uint16                      m_partOrbit;
    uint16                      m_partCamera;
    RBTimer                     m_kTimer;
    int4                        m_FBWindow;
    int2                        m_previousMousePos;
    RBVisibilityManager*        m_pHUDScene;
};

/************************************************************************************************************/

